package com.hboxs.asl.wechat;

import com.hboxs.asl.entity.Member;
import com.hboxs.asl.service.MemberRankService;
import com.hboxs.asl.service.MemberService;
import com.hboxs.asl.wechat.entity.Wechat;
import com.hboxs.asl.wechat.entity.WxUserInfo;
import com.hboxs.asl.wechat.entity.WxUserLocation;
import com.hboxs.asl.wechat.message.respone.TextMessage;
import com.hboxs.asl.wechat.payment.base.WxPayException;
import com.hboxs.asl.wechat.service.WechatService;
import com.hboxs.asl.wechat.service.WxConfigService;
import com.hboxs.asl.wechat.utils.WechatUtils;
import com.hboxs.asl.wechat.utils.WxXmlUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;

/**
 * 核心服务类
 */
@Service(value = "wxCoreService")
public class WxCoreService {
    protected Logger logger = Logger.getLogger(getClass().getName());

    @Resource(name = "wechatServiceImpl")
    private WechatService wechatService;
    @Resource(name = "memberServiceImpl")
    private MemberService memberService;
    @Resource(name = "memberRankServiceImpl")
    private MemberRankService memberRankService;
    @Resource(name = "wxConfigServiceImpl")
    private WxConfigService wxConfigService;

    /**
     * 处理微信发来的请求
     *
     * @param request 请求
     * @return 返回请求结果
     */
    public String processRequest(HttpServletRequest request) throws WxPayException {
        String respMessage = null;
        try {
            // 默认返回的文本消息内容
            String respContent = null;
            // xml请求解析
            Map<String, String> requestMap = WxXmlUtil.parseXml(request);

            // 发送方帐号（open_id）
            String fromUserName = requestMap.get("FromUserName");
            // 公众帐号
            String toUserName = requestMap.get("ToUserName");
            // 消息类型
            String msgType = requestMap.get("MsgType");

            // 回复文本消息
            TextMessage message = new TextMessage();
            message.setToUserName(fromUserName);
            message.setFromUserName(toUserName);
            message.setCreateTime(new Date().getTime());
            message.setMsgType(WxXmlUtil.RESP_MESSAGE_TYPE_TEXT);
            message.setFuncFlag(0);

            // 添加微信用户如果不存在
            Wechat wechat = wechatService.find(fromUserName);

            if (wechat == null) wechat = newWechat(fromUserName);

            // 微信用户存在 添加系统member
            if(wechat.getMember()==null){

                Member member = new Member();
                member.setUsername(wechat.getOpenid());
                member.setPassword(DigestUtils.md5Hex(wechat.getOpenid()));
                member.setEmail("@");
                member.setIsEnabled(true);
                member.setIsLocked(false);
                member.setLoginFailureCount(0);
                member.setLockedDate(null);
                member.setRegisterIp(request.getRemoteAddr());
                member.setLoginIp(request.getRemoteAddr());
                member.setLoginDate(new Date());
                member.setSafeKey(null);
                member.setMemberRank(memberRankService.findDefault());
                memberService.save(member);
                wechat.setMember(member);
                wechatService.update(wechat);
            }

            // 更新用户信息
            if(wechat.getWxUserInfo() == null) {
                updateUserInfo(wechat);
            }

            switch (msgType) {
                // 文本消息
                case WxXmlUtil.REQ_MESSAGE_TYPE_TEXT:
                    respContent = "您发送的是文本消息！";
                    break;
                // 图片消息
                case WxXmlUtil.REQ_MESSAGE_TYPE_IMAGE:
                    respContent = "您发送的是图片消息！";
                    break;
                // 地理位置消息
                case WxXmlUtil.REQ_MESSAGE_TYPE_LOCATION:
                    respContent = "您发送的是地理位置消息！";
                    break;
                // 链接消息
                case WxXmlUtil.REQ_MESSAGE_TYPE_LINK:
                    respContent = "您发送的是链接消息！";
                    break;
                // 音频消息
                case WxXmlUtil.REQ_MESSAGE_TYPE_VOICE:
                    respContent = "您发送的是音频消息！";
                    break;
                // 事件推送
                case WxXmlUtil.REQ_MESSAGE_TYPE_EVENT:
                    // 事件类型
                    String eventType = requestMap.get("Event");
                    // 事件
                    String eventKey = requestMap.get("EventKey");
                    switch (eventType) {
//                        // 自定义菜单点击事件
                        case WxXmlUtil.EVENT_TYPE_CLICK:
                            switch (eventKey) {
                                case WxXmlUtil.EVENT_TYPE_ABOUT:
                                    try {
                                        respContent = "关于【EASIN】";
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                    break;
                                case WxXmlUtil.EVENT_TYPE_JOIN:
                                    try {
                                        respContent = "加入【EASIN】";
                                    } catch (Exception e) {
                                        e.printStackTrace();
                                    }
                                    break;
                                default:
                                    return null;
                            }
                            break;

                        // 用户订阅
                        case WxXmlUtil.EVENT_TYPE_SUBSCRIBE:
                            respContent = "感谢您关注【EASIN】";
                            break;
                        // 更新地理位置
                        case WxXmlUtil.EVENT_TYPE_LOCATION:
                            String latitude = requestMap.get("Latitude");
                            String longitude = requestMap.get("Longitude");
                            String precision = requestMap.get("Precision");
                            updateLocation(fromUserName, latitude, longitude, precision);
                            return null;
                        default:
                            break;
                    }
                    break;
                default:
                    return null;
            }

            if (respContent == null || respContent.equals("")) respContent = "请求处理异常，请稍候尝试！";

            message.setContent(respContent);
            respMessage = WxXmlUtil.textMessageToXml(message);
        } catch (Exception e) {
            e.printStackTrace();
        }

        return respMessage;
    }

    /**
     * 更新地理位置
     *
     * @param username  用户名
     * @param latitude  纬度
     * @param longitude 经度
     * @param precision 精确度
     * @return 微信用户
     */
    private Wechat updateLocation(String username, String latitude, String longitude, String precision) {
        logger.info("Updating user location:{user:" + username + ",lat:" + latitude + ",lon:" + longitude + ",prec:" + precision + "}");

        Wechat wechat = wechatService.find(username);
        if (wechat == null) return wechat;

        WxUserLocation userLocation = wechat.getWxUserLocation();
        if (wechat.getWxUserLocation() == null) userLocation = new WxUserLocation();

        userLocation.setLat(latitude);
        userLocation.setLon(longitude);
        userLocation.setPrec(precision);
        wechat = wechatService.update(wechat, userLocation);

        return wechat;
    }

    /**
     * 添加新微信用户
     *
     * @param openid 微信ID
     * @return 微信用户
     */
    private Wechat newWechat(String openid) {
        // 添加微信用户
        Wechat wechat = new Wechat();
        wechat.setOpenid(openid);
        wechatService.save(wechat);

        // 更新微信用户信息
        updateUserInfo(wechat);

        return wechat;
    }

    /**
     * 更新用户信息
     *
     * @param wechat 用户微信
     * @return true or false
     */
    private boolean updateUserInfo(Wechat wechat) {
        try {
            if (StringUtils.isNotEmpty(wechat.getOpenid())) {
                WxUserInfo wxUserInfo = WechatUtils.userinfo(wxConfigService.latestAccessToken(), wechat.getOpenid(), true);
                wechatService.update(wechat, wxUserInfo);

                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        return false;
    }

}
